/**
 * @file 密码管理器服务
 * @description 提供密码管理器的核心业务逻辑
 * @author AI Assistant
 * @version 2.0.0
 * @since 2025-10-22
 * @updated 2025-10-31 - Removed master password, using fixed salt encryption
 */

import Realm from 'realm'
import { getDatabase } from '../index'
import {
  type CreateUserCredentialInput,
  type DatabaseResult,
  type DecryptedUserCredential,
  type PasswordManagerSettings,
  type QueryUserCredentialParams,
  type UpdateUserCredentialInput,
  UserCredentialModel
} from '../models/user-credential.model'
import {
  type DecryptionParams,
  decryptPassword,
  type EncryptionResult,
  encryptPassword
} from '#/utils/encryption'
import { createStorageState } from 'global-state'

/**
 * 将 Realm 对象转换为普通对象以便 IPC 传递（返回加密数据）
 */
function convertCredentialToPlainObject(credential: UserCredentialModel): any {
  return {
    _id: credential._id.toString(),
    id: credential.id,
    domain: credential.domain,
    site_name: credential.site_name,
    username: credential.username,
    encrypted_password: credential.encrypted_password,
    salt: credential.salt,
    favicon_url: credential.favicon_url,
    auto_fill_enabled: credential.auto_fill_enabled,
    is_synced: credential.is_synced,
    server_id: credential.server_id,
    last_used_at: credential.last_used_at,
    created_at: credential.created_at,
    updated_at: credential.updated_at
  }
}

/**
 * 密码管理器服务类
 */
export class PasswordManagerService {
  private static instance: PasswordManagerService
  private localSettings = createStorageState(
    'passwordManagerSettings',
    {
      enabled: true,
      auto_fill_enabled: true,
      save_prompt_enabled: true,
      sync_enabled: true
    },
    1
  )

  private constructor() {}

  /**
   * 获取服务实例（单例模式）
   */
  static getInstance(): PasswordManagerService {
    if (!PasswordManagerService.instance) {
      PasswordManagerService.instance = new PasswordManagerService()
    }
    return PasswordManagerService.instance
  }

  /**
   * 获取下一个可用的数值ID
   */
  private getNextLegacyId(realm: Realm): number {
    const allCredentials = realm.objects<UserCredentialModel>('UserCredential')
    const credentialsWithId = allCredentials.filtered('id != null').sorted('id', true)
    const lastCredential = credentialsWithId[0] as UserCredentialModel | undefined
    return (lastCredential?.id ?? 0) + 1
  }

  /**
   * 添加用户凭据
   */
  async addCredential(
    input: CreateUserCredentialInput
  ): Promise<DatabaseResult<UserCredentialModel>> {
    try {
      const realm = getDatabase()
      const now = new Date()

      // 加密密码 - 使用新的固定盐值加密
      const encryptionResult = encryptPassword(input.password)

      let newCredential: UserCredentialModel

      realm.write(() => {
        const nextId = this.getNextLegacyId(realm)
        newCredential = realm.create('UserCredential', {
          _id: new Realm.BSON.ObjectId(),
          id: nextId,
          domain: input.domain,
          site_name: input.site_name || null,
          username: input.username,
          encrypted_password: JSON.stringify(encryptionResult),
          salt: encryptionResult.salt,
          favicon_url: input.favicon_url || null,
          auto_fill_enabled: input.auto_fill_enabled ?? true,
          is_synced: false,
          server_id: null,
          last_used_at: null,
          created_at: now,
          updated_at: now
        }) as UserCredentialModel
      })

      console.log(`✅ 用户凭据添加成功: ${input.domain} - ${input.username}`)

      // 转换为普通对象以便 IPC 传递
      const credentialData = convertCredentialToPlainObject(newCredential!)

      return {
        success: true,
        data: credentialData
      }
    } catch (error) {
      console.error('添加用户凭据失败:', error)
      return {
        success: false,
        error: error instanceof Error ? error.message : '添加凭据失败'
      }
    }
  }

  /**
   * 查询用户凭据（返回加密数据）
   */
  async queryCredentials(
    params: QueryUserCredentialParams = {}
  ): Promise<DatabaseResult<UserCredentialModel[]>> {
    try {
      const realm = getDatabase()
      let query = realm.objects<UserCredentialModel>('UserCredential')

      // 应用过滤条件
      if (params.domain) {
        query = query.filtered('domain CONTAINS[c] $0', params.domain)
      }
      if (params.username) {
        query = query.filtered('username CONTAINS[c] $0', params.username)
      }
      if (params.site_name) {
        query = query.filtered('site_name CONTAINS[c] $0', params.site_name)
      }
      if (params.auto_fill_enabled !== undefined) {
        query = query.filtered('auto_fill_enabled == $0', params.auto_fill_enabled)
      }
      if (params.is_synced !== undefined) {
        query = query.filtered('is_synced == $0', params.is_synced)
      }

      // 排序
      const sortBy = params.sortBy || 'updated_at'
      const sortOrder = params.sortOrder === 'asc'
      query = query.sorted(sortBy, !sortOrder)

      // 分页
      let results = Array.from(query) as UserCredentialModel[]
      if (params.offset) {
        results = results.slice(params.offset)
      }
      if (params.limit) {
        results = results.slice(0, params.limit)
      }

      // 转换为普通对象以便 IPC 传递
      const credentialsData = results.map(convertCredentialToPlainObject)

      return {
        success: true,
        data: credentialsData,
        count: query.length
      }
    } catch (error) {
      console.error('查询用户凭据失败:', error)
      return {
        success: false,
        error: error instanceof Error ? error.message : '查询凭据失败'
      }
    }
  }

  /**
   * 获取用户凭据（解密密码）
   */
  async getDecryptedCredentials(
    params: QueryUserCredentialParams = {}
  ): Promise<DatabaseResult<DecryptedUserCredential[]>> {
    try {
      const result = await this.queryCredentials(params)
      if (!result.success || !result.data) {
        return { success: false, error: result.error, data: [] }
      }

      const credentials: DecryptedUserCredential[] = result.data.map(credential => {
        try {
          // 解密密码 - 使用新的固定盐值解密
          const encryptionData: EncryptionResult = JSON.parse(credential.encrypted_password)
          const decryptionParams: DecryptionParams = {
            encryptedData: encryptionData.encryptedData,
            iv: encryptionData.iv,
            salt: encryptionData.salt,
            authTag: encryptionData.authTag
          }
          const decryptedPassword = params.domain
            ? decryptPassword(decryptionParams)
            : encryptionData.encryptedData

          return {
            _id: credential._id.toString(),
            id: credential.id,
            domain: credential.domain,
            site_name: credential.site_name,
            username: credential.username,
            password: decryptedPassword,
            favicon_url: credential.favicon_url,
            auto_fill_enabled: credential.auto_fill_enabled,
            is_synced: credential.is_synced,
            server_id: credential.server_id,
            last_used_at: credential.last_used_at,
            created_at: credential.created_at,
            updated_at: credential.updated_at
          }
        } catch (error) {
          console.error(`解密密码失败 (${credential.domain}):`, error)
          // 如果解密失败，返回空密码
          return {
            _id: credential._id.toString(),
            id: credential.id,
            domain: credential.domain,
            site_name: credential.site_name,
            username: credential.username,
            password: '',
            favicon_url: credential.favicon_url,
            auto_fill_enabled: credential.auto_fill_enabled,
            is_synced: credential.is_synced,
            server_id: credential.server_id,
            last_used_at: credential.last_used_at,
            created_at: credential.created_at,
            updated_at: credential.updated_at
          }
        }
      })

      return {
        success: true,
        data: credentials,
        count: credentials.length
      }
    } catch (error) {
      console.error('获取解密凭据失败:', error)
      return {
        success: false,
        error: error instanceof Error ? error.message : '获取解密凭据失败'
      }
    }
  }

  /**
   * 更新用户凭据
   */
  async updateCredential(
    input: UpdateUserCredentialInput
  ): Promise<DatabaseResult<UserCredentialModel>> {
    try {
      const realm = getDatabase()
      const credential = realm.objectForPrimaryKey(
        'UserCredential',
        new Realm.BSON.ObjectId(input.id)
      ) as UserCredentialModel

      if (!credential) {
        return { success: false, error: '凭据不存在' }
      }

      realm.write(() => {
        if (input.site_name !== undefined) {
          credential.site_name = input.site_name
        }
        if (input.username !== undefined) {
          credential.username = input.username
        }
        if (input.password !== undefined) {
          // 重新加密密码 - 使用新的固定盐值加密
          const encryptionResult = encryptPassword(input.password)
          credential.encrypted_password = JSON.stringify(encryptionResult)
          credential.salt = encryptionResult.salt
        }
        if (input.favicon_url !== undefined) {
          credential.favicon_url = input.favicon_url
        }
        if (input.auto_fill_enabled !== undefined) {
          credential.auto_fill_enabled = input.auto_fill_enabled
        }

        credential.updated_at = new Date()
        credential.is_synced = false // 标记为需要同步
      })

      console.log(`✅ 用户凭据更新成功: ${credential.domain} - ${credential.username}`)

      // 转换为普通对象以便 IPC 传递
      const credentialData = convertCredentialToPlainObject(credential)

      return {
        success: true,
        data: credentialData
      }
    } catch (error) {
      console.error('更新用户凭据失败:', error)
      return {
        success: false,
        error: error instanceof Error ? error.message : '更新凭据失败'
      }
    }
  }

  /**
   * 删除用户凭据
   */
  async deleteCredential(id: string): Promise<DatabaseResult<boolean>> {
    try {
      const realm = getDatabase()
      const objectId = new Realm.BSON.ObjectId(id)
      const credential = realm.objectForPrimaryKey(
        UserCredentialModel,
        objectId
      ) as UserCredentialModel | null
      if (!credential) {
        return { success: false, error: '凭据不存在' }
      }
      realm.write(() => {
        realm.delete(credential)
      })

      return {
        success: true,
        data: true
      }
    } catch (error) {
      console.error('删除用户凭据失败:', id, error)
      return {
        success: false,
        error: error instanceof Error ? error.message : '删除凭据失败'
      }
    }
  }

  /**
   * 更新最后使用时间
   */
  async updateLastUsed(id: string): Promise<DatabaseResult<boolean>> {
    try {
      const realm = getDatabase()
      const credential = realm.objectForPrimaryKey(
        'UserCredential',
        new Realm.BSON.ObjectId(id)
      ) as UserCredentialModel

      if (!credential) {
        return { success: false, error: '凭据不存在' }
      }

      realm.write(() => {
        credential.last_used_at = new Date()
        credential.updated_at = new Date()
      })

      return {
        success: true,
        data: true
      }
    } catch (error) {
      console.error('更新最后使用时间失败:', error)
      return {
        success: false,
        error: error instanceof Error ? error.message : '更新失败'
      }
    }
  }

  /**
   * 获取密码管理器设置
   */
  async getSettings(): Promise<DatabaseResult<PasswordManagerSettings>> {
    return { success: true, data: JSON.parse(JSON.stringify(this.localSettings.state)) }
  }

  /**
   * 同步凭据到云端
   * 将未同步的凭据上传到服务器
   */
  async syncToCloud(): Promise<DatabaseResult<{ synced: number; failed: number }>> {
    try {
      const realm = getDatabase()

      // 获取所有未同步的凭据
      const unsyncedCredentials = realm
        .objects<UserCredentialModel>('UserCredential')
        .filtered('is_synced == false')

      if (unsyncedCredentials.length === 0) {
        return { success: true, data: { synced: 0, failed: 0 } }
      }

      let syncedCount = 0
      let failedCount = 0

      // 逐个同步凭据
      for (const credential of unsyncedCredentials) {
        try {
          // 准备同步数据
          const syncData = {
            id: credential.server_id || 0,
            domain: credential.domain,
            site_name: credential.site_name || undefined,
            username: credential.username,
            encrypted_password: credential.encrypted_password,
            favicon_url: credential.favicon_url || undefined,
            auto_fill_enabled: credential.auto_fill_enabled ? 1 : 0,
            created_at: credential.created_at.getTime(),
            updated_at: credential.updated_at.getTime()
          }

          // 这里应该调用云端API，但由于是主进程，我们需要通过IPC通知渲染进程
          const base = process.env.VITE_API_BASE_URL
          const res = await fetch(`${base}/browser/savePassword`, {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json'
            },
            body: JSON.stringify({ save_data: syncData })
          })
          const data = (await res.json()) as {
            code: number
            message: string
            data: { save_data: F2.user.UserCredential }
          }
          if (data.code !== 0) {
            throw new Error(data.message)
          }
          console.log('同步数据::', syncData)
          console.log('同步响应::', res.ok, data)

          // 暂时标记为已同步
          realm.write(() => {
            credential.is_synced = true
            credential.updated_at = new Date()
            credential.server_id = String(data.data.save_data.id || 0)
          })

          syncedCount++
        } catch (error) {
          console.error(`同步凭据失败 (${credential.domain}):`, error)
          failedCount++
        }
      }

      console.log(`✅ 云端同步完成: ${syncedCount} 成功, ${failedCount} 失败`)

      return {
        success: true,
        data: { synced: syncedCount, failed: failedCount }
      }
    } catch (error) {
      console.error('云端同步失败:', error)
      return {
        success: false,
        error: error instanceof Error ? error.message : '云端同步失败'
      }
    }
  }

  /**
   * 从云端拉取凭据
   * 下载服务器上的凭据并合并到本地
   */
  async syncFromCloud(
    cloudCredentials: F2.user.UserCredential[]
  ): Promise<DatabaseResult<{ imported: number; updated: number }>> {
    try {
      const realm = getDatabase()
      let importedCount = 0
      let updatedCount = 0

      for (const cloudCred of cloudCredentials) {
        try {
          // 查找是否已存在相同的凭据（通过 server_id 或 domain+username）
          let existingCredential: UserCredentialModel | null = null

          if (cloudCred.id) {
            const credentials = realm
              .objects<UserCredentialModel>('UserCredential')
              .filtered('server_id == $0', cloudCred.id.toString())
            existingCredential =
              credentials.length > 0 ? (credentials[0] as UserCredentialModel) : null
          }

          if (!existingCredential) {
            // 通过 domain 和 username 查找
            const credentials = realm
              .objects<UserCredentialModel>('UserCredential')
              .filtered('domain == $0 AND username == $1', cloudCred.domain, cloudCred.username)
            existingCredential =
              credentials.length > 0 ? (credentials[0] as UserCredentialModel) : null
          }

          realm.write(() => {
            const auto_fill_enabled =
              cloudCred.auto_fill_enabled === undefined
                ? true
                : Boolean(cloudCred.auto_fill_enabled)
            if (existingCredential) {
              // 更新现有凭据
              existingCredential.encrypted_password = cloudCred.encrypted_password
              existingCredential.site_name = cloudCred.site_name || null
              existingCredential.favicon_url = cloudCred.favicon_url || null
              existingCredential.auto_fill_enabled = auto_fill_enabled
              existingCredential.server_id = cloudCred.id?.toString() || null
              existingCredential.updated_at = new Date()
              updatedCount++
            } else {
              // 创建新凭据
              const nextId = this.getNextLegacyId(realm)
              realm.create('UserCredential', {
                _id: new Realm.BSON.ObjectId(),
                id: nextId,
                domain: cloudCred.domain,
                site_name: cloudCred.site_name || null,
                username: cloudCred.username,
                encrypted_password: cloudCred.encrypted_password,
                salt: '', // 云端数据已包含在 encrypted_password 中
                favicon_url: cloudCred.favicon_url || null,
                auto_fill_enabled,
                is_synced: true,
                server_id: cloudCred.id?.toString() || null,
                last_used_at: null,
                created_at: new Date(cloudCred.created_at || Date.now()),
                updated_at: new Date(cloudCred.updated_at || Date.now())
              })
              importedCount++
            }
          })
        } catch (error) {
          console.error(`导入云端凭据失败 (${cloudCred.domain}):`, error)
        }
      }

      console.log(`✅ 从云端同步完成: ${importedCount} 新增, ${updatedCount} 更新`)

      return {
        success: true,
        data: { imported: importedCount, updated: updatedCount }
      }
    } catch (error) {
      console.error('从云端同步失败:', error)
      return {
        success: false,
        error: error instanceof Error ? error.message : '从云端同步失败'
      }
    }
  }
}
